/*
 * SPDX-FileCopyrightText: 2006 Uwe Stuehler <uwe@openbsd.org>
 *
 * SPDX-License-Identifier: ISC
 *
 * SPDX-FileContributor: 2016-2021 Espressif Systems (Shanghai) CO LTD
 */
/*
 * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#pragma once

#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "sdmmc_system.h"

#ifdef __cplusplus
extern "C" {
#endif

/* 定义错误常量. */
#define SDMMC_OK   0  /*!< sdmmc_err_t的值, 表示成功(没有错误). */
#define SDMMC_FAIL -1 /*!< sdmmc_err_t的值, 表示失败. */

#define SDMMC_ERR_NO_MEM            0x101 /*!< 内存不足. */
#define SDMMC_ERR_INVALID_ARG       0x102 /*!< 参数无效. */
#define SDMMC_ERR_INVALID_STATE     0x103 /*!< 状态无效. */
#define SDMMC_ERR_INVALID_SIZE      0x104 /*!< 大小无效. */
#define SDMMC_ERR_NOT_FOUND         0x105 /*!< 未找到请求的资源. */
#define SDMMC_ERR_NOT_SUPPORTED     0x106 /*!< 不支持的操作或特性. */
#define SDMMC_ERR_TIMEOUT           0x107 /*!< Operation timed out */
#define SDMMC_ERR_INVALID_RESPONSE  0x108 /*!< Received response was invalid */
#define SDMMC_ERR_INVALID_CRC       0x109 /*!< CRC or checksum was invalid */
#define SDMMC_ERR_INVALID_VERSION   0x10A /*!< Version was invalid */
#define SDMMC_ERR_INVALID_MAC       0x10B /*!< MAC address was invalid */
#define SDMMC_ERR_NOT_FINISHED      0x10C /*!< There are items remained to retrieve */

#define SDMMC_ERR_WIFI_BASE         0x3000 /*!< Starting number of WiFi error codes */
#define SDMMC_ERR_MESH_BASE         0x4000 /*!< Starting number of MESH error codes */
#define SDMMC_ERR_FLASH_BASE        0x6000 /*!< Starting number of flash error codes */
#define SDMMC_ERR_HW_CRYPTO_BASE    0xc000 /*!< Starting number of HW cryptography module error codes */
#define SDMMC_ERR_MEMPROT_BASE      0xd000 /*!< Starting number of Memory Protection API error codes */

/**
 * Decoded values from SD card Card Specific Data register
 */
typedef struct {
    int csd_ver;                    /*!< CSD structure format */
    int mmc_ver;                    /*!< MMC version (for CID format) */
    int capacity;                   /*!< total number of sectors */
    int sector_size;                /*!< sector size in bytes */
    int read_block_len;             /*!< block length for reads */
    int card_command_class;         /*!< Card Command Class for SD */
    int tr_speed;                   /*!< Max transfer speed */
} sdmmc_csd_t;

/**
 * Decoded values from SD card Card IDentification register
 */
typedef struct {
    int mfg_id;                     /*!< manufacturer identification number */
    int oem_id;                     /*!< OEM/product identification number */
    char name[8];                   /*!< product name (MMC v1 has the longest) */
    int revision;                   /*!< product revision */
    int serial;                     /*!< product serial number */
    int date;                       /*!< manufacturing date */
} sdmmc_cid_t;

/**
 * Decoded values from SD Configuration Register
 * Note: When new member is added, update reserved bits accordingly
 */
typedef struct {
    uint32_t sd_spec: 4;            /*!< SD Physical layer specification version, reported by card */
    uint32_t erase_mem_state: 1;    /*!< data state on card after erase whether 0 or 1 (card vendor dependent) */
    uint32_t bus_width: 4;          /*!< bus widths supported by card: BIT(0) — 1-bit bus, BIT(2) — 4-bit bus */
    uint32_t reserved: 23;          /*!< reserved for future expansion */
    uint32_t rsvd_mnf;              /*!< reserved for manufacturer usage */
} sdmmc_scr_t;

/**
 * Decoded values from SD Status Register
 * Note: When new member is added, update reserved bits accordingly
 */
typedef struct {
    uint32_t alloc_unit_kb: 16;     /*!< Allocation unit of the card, in multiples of kB (1024 bytes) */
    uint32_t erase_size_au: 16;     /*!< Erase size for the purpose of timeout calculation, in multiples of allocation unit */
    uint32_t cur_bus_width: 2;      /*!< SD current bus width */
    uint32_t discard_support: 1;    /*!< SD discard feature support */
    uint32_t fule_support: 1;       /*!< SD FULE (Full User Area Logical Erase) feature support */
    uint32_t erase_timeout: 6;      /*!< Timeout (in seconds) for erase of a single allocation unit */
    uint32_t erase_offset: 2;       /*!< Constant timeout offset (in seconds) for any erase operation */
    uint32_t reserved: 20;          /*!< reserved for future expansion */
} sdmmc_ssr_t;

/**
 * Decoded values of Extended Card Specific Data
 */
typedef struct {
    uint8_t rev;                    /*!< Extended CSD Revision */
    uint8_t power_class;            /*!< Power class used by the card */
    uint8_t erase_mem_state;        /*!< data state on card after erase whether 0 or 1 (card vendor dependent) */
    uint8_t sec_feature;            /*!< secure data management features supported by the card */
} sdmmc_ext_csd_t;

/**
 * SD/MMC命令响应缓冲.
 */
typedef uint32_t sdmmc_response_t[4];

/**
 * SD SWITCH_FUNC响应缓冲.
 */
typedef struct {
    uint32_t data[512 / 8 / sizeof(uint32_t)];  /*!< response data */
} sdmmc_switch_func_rsp_t;

/**
 * SD/MMC命令信息结构体.
 */
typedef struct {
    uint32_t opcode;                /*!< SD/MMC命令编码. */
    uint32_t arg;                   /*!< SD/MMC命令参数 */
    sdmmc_response_t response;      /*!< 响应缓冲. */
    void* data;                     /*!< 要发送或读取的数据缓冲区. */
    size_t datalen;                 /*!< 数据缓冲区长度. */
    size_t blklen;                  /*!< 块长度. */
    int flags;                      /*!< 命令标识, 加下文. */
/** @cond */
#define SCF_ITSDONE      0x0001     /*!< 命令完成. */
#define SCF_CMD(flags)   ((flags) & 0x00f0)
#define SCF_CMD_AC       0x0000
#define SCF_CMD_ADTC     0x0010
#define SCF_CMD_BC       0x0020
#define SCF_CMD_BCR      0x0030
#define SCF_CMD_READ     0x0040     /*!< 读取命令(预期数据). */
#define SCF_RSP_BSY      0x0100
#define SCF_RSP_136      0x0200
#define SCF_RSP_CRC      0x0400
#define SCF_RSP_IDX      0x0800
#define SCF_RSP_PRESENT  0x1000
/* 响应类型 */
#define SCF_RSP_R0       0 /*!< none */
#define SCF_RSP_R1       (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_IDX)
#define SCF_RSP_R1B      (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_IDX | SCF_RSP_BSY)
#define SCF_RSP_R2       (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_136)
#define SCF_RSP_R3       (SCF_RSP_PRESENT)
#define SCF_RSP_R4       (SCF_RSP_PRESENT)
#define SCF_RSP_R5       (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_IDX)
#define SCF_RSP_R5B      (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_IDX | SCF_RSP_BSY)
#define SCF_RSP_R6       (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_IDX)
#define SCF_RSP_R7       (SCF_RSP_PRESENT | SCF_RSP_CRC | SCF_RSP_IDX)
/* 特殊标志 */
#define SCF_WAIT_BUSY    0x2000     /*!< 等待卡忙信号完成后再返回. */
/** @endcond */
    sdmmc_err_t error;              /*!< 返回传输错误. */
    uint32_t timeout_ms;            /*!< 响应超时时间, 以毫秒为单位. */
} sdmmc_command_t;

/**
 * 该结构定义了SD/MMC主机的属性和可供上层使用的SD/MMC主机功能.
 */
typedef struct {
    uint32_t flags;                 /*!< 定义主机属性的标志. */
#define SDMMC_HOST_FLAG_1BIT        (1 << 0) /*!< 主机支持1线SD和MMC协议. */
#define SDMMC_HOST_FLAG_4BIT        (1 << 1) /*!< 主机支持4线SD和MMC协议. */
#define SDMMC_HOST_FLAG_8BIT        (1 << 2) /*!< 主机支持8线MMC协议. */
#define SDMMC_HOST_FLAG_SPI         (1 << 3) /*!< 主机支持SPI协议. */
#define SDMMC_HOST_FLAG_DDR         (1 << 4) /*!< 主机支持DDR模式. */
#define SDMMC_HOST_FLAG_DEINIT_ARG  (1 << 5) /*!< 主机函数'deinit'被接口调用调用. */
    int slot;                       /*!< 接口号, 传递给主机函数. */
    int max_freq_khz;               /*!< 主机支持的最大频率. */
#define SDMMC_FREQ_DEFAULT          25000 /*!< SD/MMC默认模式, 0~25MHz. */
#define SDMMC_FREQ_HIGHSPEED        50000 /*!< SD/MMC高速模式, 0~50MHz. */
#define SDMMC_FREQ_PROBING          400   /*!< SD/MMC探测速度, 400KHz. */
#define SDMMC_FREQ_50M              50000 /*!< MMC速度为50MHz, 单位: KHz */
#define SDMMC_FREQ_52M              52000 /*!< MMC速度为52MHz, 单位: KHz */
#define SDMMC_FREQ_26M              26000 /*!< MMC速度为26MHz, 单位: KHz */
    int type;                       /*!< 主机类型. */
    float io_voltage;               /*!< 控制器使用的I/O电压(不支持电压切换). */
    sdmmc_err_t (*set_bus_width)(int slot, size_t width); /*!< 主机函数: 设置总线宽度. */
    size_t (*get_bus_width)(int slot); /*!< 主机函数: 获取总线宽度. */
    sdmmc_err_t (*set_bus_ddr_mode)(int slot, bool ddr_enable); /*!< 主机函数: 设置DDR模式. */
    sdmmc_err_t (*set_card_clk)(int slot, uint32_t freq_khz); /*!< 主机函数: 设置卡时钟频率. */
    sdmmc_err_t (*do_transaction)(int slot, sdmmc_command_t* cmdinfo); /*!< 主机函数: 执行事务处理. */
    sdmmc_err_t (*io_int_enable)(int slot); /*!< 主机函数: 开启SDIO中断. */
    sdmmc_err_t (*io_int_wait)(int slot, tick_type_t timeout_ticks); /*!< 主机函数: 等待SDIO中断被激活. */
    int command_timeout_ms; /*!< 单个命令的超时时间, 以毫秒为单位. 设置为0, 使用默认值. */
    sdmmc_err_t (*get_real_freq)(int slot, int* real_freq); /*!< 主机函数: 获取真实工作频率, 基于SDMMC控制器设置. */
} sdmmc_host_t;

/**
 * SD/MMC卡信息结构体.
 */
typedef struct {
    sdmmc_host_t host;              /*!< 与卡相关联的主机. */
    uint32_t ocr;                   /*!< OCR(操作条件寄存器)的值. */
    union {
        sdmmc_cid_t cid;            /*!< 已解码的CID(卡标识)寄存器的值. */
        sdmmc_response_t raw_cid;   /*!< 取数据传输模式CSD后, 未解码的MMC卡原始CID的值. */
    };
    sdmmc_csd_t csd;                /*!< 已解码的CSD(卡特定数据)寄存器的值 */
    sdmmc_scr_t scr;                /*!< 已解码的SCR(SD卡配置寄存器)的值. */
    sdmmc_ssr_t ssr;                /*!< 已解码的SSR(SD状态寄存器)的值. */
    sdmmc_ext_csd_t ext_csd;        /*!< 已解码的EXT_CSD(扩展卡特定数据)寄存器的值. */
    uint16_t rca;                   /*!< RCA(相关卡地址). */
    uint16_t max_freq_khz;          /*!< 卡支持的最大工作频率, 单位: KHz */
    int real_freq_khz;              /*!< 主机控制器配置的真实工作频率, 单位: KHz */
    uint32_t is_mem : 1;            /*!< 存储卡标识位. */
    uint32_t is_sdio : 1;           /*!< IO卡标识位. */
    uint32_t is_mmc : 1;            /*!< MMC卡标识位. */
    uint32_t num_io_functions : 3;  /*!< 当is_sdio为1时, 卡包含IO功能的个数. */
    uint32_t log_bus_width : 2;     /*!< log2(卡支持的总线宽度). */
    uint32_t is_ddr : 1;            /*!< 卡支持DDR模式标识位. */
    uint32_t reserved : 23;         /*!< 为未来扩展预留. */
} sdmmc_card_t;

/**
 * 用于SD/MMC卡信息查找的结构体.
 */
typedef struct {
    uint32_t sector_size;
    uint64_t sector_num;
    uint32_t is_mem : 1;            /*!< 存储卡标识位. */
    uint32_t is_sdio : 1;           /*!< IO卡标识位. */
    uint32_t is_mmc : 1;            /*!< MMC卡标识位. */
    uint32_t is_ddr : 1;            /*!< 卡支持DDR模式标识位. */
    uint32_t is_sdhc : 1;
} sdmmc_card_info_t;

/**
 * SD/MMC擦除命令(38)参数.
 * SD:
 *  ERASE: 擦除写块, 物理/硬擦除.
 *
 *  DISCARD: 卡可以部分或全部释放被丢弃的块.
 *  在丢弃操作之后，先前写入的数据可能由主机部分或全部读取，这取决于卡的实现.
 *
 * MMC:
 *  ERASE: 是否裁剪, 应用擦除操作写块而不是擦除组.
 *
 *  DISCARD: 丢弃功能允许主机识别不再需要的数据, 以便设备可以在必要时在后台
 *  擦除事件中擦除数据. 适用于写块而不是擦除组在丢弃操作后, 原始数据可能会被
 *  主机保留部分或全部访问, 这取决于设备.
 *
 */
typedef enum {
    SDMMC_ERASE_ARG = 0,            /*!< SD上的擦除操作，MMC上的裁剪操作. */
    SDMMC_DISCARD_ARG = 1,          /*!< 丢弃SD/MMC操作. */
} sdmmc_erase_arg_t;

#ifdef __cplusplus
}
#endif
